package jee.boot.module.bpm.service;

import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import jee.boot.common.CommonConstant;
import jee.boot.common.basic.CrudService;
import jee.boot.common.basic.Page;
import jee.boot.common.basic.ServiceException;
import jee.boot.common.basic.result.MapData;
import jee.boot.common.utils.JsonMapper;
import jee.boot.common.utils.StringUtils;
import jee.boot.entity.bpm.BpmConstant;
import jee.boot.module.bpm.dao.BusinessTableDao;
import jee.boot.entity.bpm.BusinessTable;
import jee.boot.module.bpm.table.TableExecutor;
import jee.boot.module.bpm.table.mysql.AuditFieldUtils;
import jee.boot.module.bpm.table.mysql.model.FormTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 表单设计_业务实体表
 */
@Service
public class BusinessTableService extends CrudService<BusinessTableDao, BusinessTable> {
    @Autowired
    private TableExecutor tableExecutor;

    @Cacheable(value = "businessTable", key = "#entity.entityKey")
    @Override
    public BusinessTable get(BusinessTable entity) {
        return super.get(entity);
    }

    @Override
    public void save(BusinessTable entity) {
        uniquenessCheck(entity, "name");
        // 只有内部表才会同步表结构
        if (StringUtils.equals(BpmConstant.BPM_TABLE_EXTERNAL_INNER, entity.getExternal())) {
            int i = tableExecutor.existTable(new FormTable(entity.getName()));
            if (i > 0) {
                throw new ServiceException(1425, MapData.instance().put("name", entity.getName()).data());
            }
            checkAndSupplementAuditFields(entity);
            tableExecutor.syncTable(entity);
        }
        super.save(entity);

    }


    @Caching(evict = {
            @CacheEvict(value = "businessTable", key = "#entity.entityKey"),
    })
    @Override
    public void update(BusinessTable entity) {
        uniquenessCheck(entity, "name");
        // 只有内部表才会同步表结构
        if (StringUtils.equals(BpmConstant.BPM_TABLE_EXTERNAL_INNER, entity.getExternal())) {
            checkAndSupplementAuditFields(entity);
            tableExecutor.syncTable(entity);
        }
        super.update(entity);
    }

    @Caching(evict = {
            @CacheEvict(value = "businessTable", key = "#entity.entityKey"),
    })
    @Override
    public void delete(BusinessTable entity) {
        super.delete(entity);
        // 只有内部表才会同步表结构
        if (StringUtils.equals(BpmConstant.BPM_TABLE_EXTERNAL_INNER, entity.getExternal())) {
            FormTable formTable = new FormTable();
            formTable.setName(entity.getName());
            tableExecutor.dropTable(formTable);
        }
    }

    /**
     * 检查并补充审计字段
     *
     * @param entity
     */
    private void checkAndSupplementAuditFields(BusinessTable entity) {
        List<Map<String, Object>> columnList = entity.getColumnList();

        Set<Object> columnSet = null;
        if (columnList != null && !columnList.isEmpty()) {
            columnSet = columnList.stream().map(c -> c.get("fieldName")).collect(Collectors.toSet());
        } else {
            columnSet = Sets.newHashSet();
        }
        boolean isUpdate = false;
        for (String field : CommonConstant.AUDIT_FIELDS) {
            if (!columnSet.contains(field)) {
                Map<String, Object> auditField = AuditFieldUtils.createAuditField(field);
                if (auditField != null) {
                    columnList.add(auditField);
                    isUpdate = true;
                }
            }
        }
        if (isUpdate) {
            entity.setColumnList(columnList);
        }

    }

    public Page<FormTable> tableList(FormTable entity) {
        Page<FormTable> page = entity.getPage();
        if (page == null) {
            page = new Page<FormTable>(1, 10);
            entity.setPage(page);
        }
        if (page.getPageSize() < 0) {
            page.setPageSize(0);
        }
        com.github.pagehelper.Page<FormTable> startPage = PageHelper.startPage(page.getPageNo(), page.getPageSize(), true, true, true);
        page.setList(tableExecutor.findTableList(entity));
        page.setCount(startPage.getTotal());
        page.setPageNo(startPage.getPageNum());
        page.setPageSize(startPage.getPageSize());
        return page;
    }


    public BusinessTable getFromTable(FormTable entity) {
        FormTable table = tableExecutor.findTable(entity);
        List<Map<String, Object>> tableColumns = tableExecutor.findTableColumns(table);
        tableColumns.stream().filter(column ->
                CommonConstant.AUDIT_COLUMNS.contains(column.get("columnName"))
        ).forEach(column -> {
            column.put("auditField",BpmConstant.SYS_YES);
        });
        BusinessTable businessTable = new BusinessTable();
        businessTable.setName(table.getName());
        businessTable.setAlias(StringUtils.toCamelCase(table.getName()));
        businessTable.setComment(table.getComment());
        businessTable.setColumnList(tableColumns);
        businessTable.setExternal(BpmConstant.BPM_TABLE_EXTERNAL_OUTER);
        return businessTable;
    }

    public static void main(String[] args) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("a", Lists.newArrayList());
        map.put("b", null);
        map.put("c", new String[]{"1", "2"});
        map.put("e", new HashMap<String, Object>() {{
            put("11", "11");
            put("12", 22);
            put("13", new Date());
            put("14", null);
        }});
        System.out.println(map);
        String jsonString = JsonMapper.toJsonString(map);
        System.out.println(jsonString);
        Map fromJsonString = JsonMapper.fromJsonString(jsonString, Map.class);
        System.out.println(JsonMapper.toJsonString(fromJsonString));
    }
}
